import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import {
  CustomException,
  ErrorCode,
} from 'src/common/exceptions/custom.exception';
import { ACCESS_TOKEN_EXPIRATION_TIME } from '../caches/constants';
import { MemoryService } from '../caches/memory.service';
import { UsersService } from '../users/users.service';
import { AuthService } from './auth.service';
import { jwtConstants } from './constants';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly userService: UsersService,
    private readonly authService: AuthService,
    private readonly memoryService: MemoryService,
  ) {
    console.log('JwtStrategy', ExtractJwt.fromAuthHeaderAsBearerToken());
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtConstants.secret,
      passReqToCallback: true,
    });
  }

  async validate(req, payload: any) {
    const user = await this.userService.findOne(payload.username);
    if (!user) {
      throw new CustomException(ErrorCode.ERR_11001);
    }
    // 从请求头中提取JWT
    const reqToken = ExtractJwt.fromAuthHeaderAsBearerToken()(req);
    // 从Redis中获取用户访问令牌
    const accessToken = await this.memoryService.get(
      this.authService.getAccessTokenKey(payload),
    );
    // 如果请求令牌不等于访问令牌
    if (reqToken !== accessToken) {
      this.memoryService.del(this.authService.getAccessTokenKey(payload));
      throw new HttpException(ErrorCode.ERR_11002, HttpStatus.UNAUTHORIZED);
    }
    // 延长token过期时间
    this.memoryService.set(
      this.authService.getAccessTokenKey(payload),
      accessToken,
      ACCESS_TOKEN_EXPIRATION_TIME,
    );
    return { userId: payload.sub, username: payload.username };
  }
}
